package com.group9.handinhand.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.group9.handinhand.dao.ActivityDao;
import com.group9.handinhand.dao.CommunityDao;
import com.group9.handinhand.dao.RequestDao;
import com.group9.handinhand.dao.UserDao;
import com.group9.handinhand.dao.model.Community;
import com.group9.handinhand.dao.model.Goods;
import com.group9.handinhand.dao.model.Offer;
import com.group9.handinhand.dao.model.Request;
import com.group9.handinhand.dao.model.RequestPost;
import com.group9.handinhand.dao.model.RequestResponse;
import com.group9.handinhand.dao.model.Services;
import com.group9.handinhand.dao.model.Skill;
import com.group9.handinhand.dao.model.User;
import com.group9.handinhand.service.so.ActivityEnums.ActivityType;
import com.group9.handinhand.service.so.CommunitySO;
import com.group9.handinhand.service.so.OfferSO;
import com.group9.handinhand.service.so.RequestPostSO;
import com.group9.handinhand.service.so.RequestResponseSO;
import com.group9.handinhand.service.so.RequestSO;
import com.group9.handinhand.service.so.SkillSO;
import com.group9.handinhand.service.so.UserSO;
import com.group9.handinhand.service.so.UserTagSO;

@Transactional
@Service("requestService")
public class RequestServiceImpl implements RequestService {
	
	@Autowired
	ActivityDao activityDao;
	
	@Autowired
	RequestDao requestDao;
	
	@Autowired
	CommunityDao communityDao;
	
	@Autowired
	UserDao userDao;
	/**
	 * Saves the request with request, user and community id 
	 * @param so
	 * @param user
	 * @param communityId
	 */
	@Override
	public RequestSO saveRequest(RequestSO so, UserSO user, Long communityId) {
		
		Goods goods = null;
		Services service = null;
		
		if(so.getGoods() != null) {
			goods = activityDao.saveGoods(so.getGoods().convertToModelObject());
		}
		if(so.getService() != null) {
			SkillSO skillSO = so.getService().getRequiredSkill();
//			aynı isimle skilleri kaydetmesin
			Skill skill = activityDao.saveSkill(skillSO.convertToModelObject());
			service = so.getService().convertToModelObject();
			service.setRequiredSkill(skill);
			service = activityDao.saveService(service);
		}
		
		Community community = communityDao.findCommunityById(communityId);
		CommunitySO communitySO = community.convertToServiceObject();
		so.getModerators().addAll(communitySO.getModerators());
		
		boolean userModerator = false;
		for (UserSO moderator : communitySO.getModerators()) {
			 if(moderator.equals(user)) {
				 userModerator = true;
			 }
		}
		if(!userModerator)
			so.getModerators().add(user);
		
		Request model = so.convertToModelObject();
		
		model.setCommunity(community);
		
		model.setCreator(userDao.findUserById(user.getId()));
		model.setGoods(goods);
		model.setService(service);
		
		model = requestDao.saveRequest(model);
		if(model != null)
			return model.convertToServiceObject();
		return null;
	}
	/**
	 * Gets request with request id.
	 * @param requestId
	 * @return request service object
	 */
	@Override
	public RequestSO getRequestById(Long requestId) {
		Request model = requestDao.findRequestById(requestId);
		if(model != null)
			return model.convertToServiceObject();
		return null;
	}
	/**
	 * Gets the requests that are responded by the user.
	 * @param user
	 * @return the list of requests
	 */
	@Override
	public List<RequestSO> getRespondedRequestsByUser(UserSO user) {
		List<Request> modelList = requestDao.findRespondedRequestsByUser(user.convertToModelObject());
		List<RequestSO> soList = new ArrayList<RequestSO>();
		for (Request model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	/**
	 * Gets  requests with tag. 
	 * @param tag
	 * @return the list of requests
	 */
	@Override
	public List<RequestSO> getRequestsByTag(UserTagSO tag) {
		List<Request> modelList = requestDao.findRequestsByTag(tag);
		List<RequestSO> soList = new ArrayList<RequestSO>();
		for (Request model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	/**
	 * Gets requests with tag name
	 * @param tag name
	 * @return the list of requests
	 */
	@Override
	public List<RequestSO> getRequestsByTagName(String keyword) {
		List<Request> modelList = requestDao.findRequestsByTagName(keyword);
		List<RequestSO> soList = new ArrayList<RequestSO>();
		for (Request model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	
	@Override
	public List<RequestSO> getRequestsByName(String keyword) {
		List<Request> modelList = requestDao.findRequestsByName(keyword);
		List<RequestSO> soList = new ArrayList<RequestSO>();
		for (Request model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	@Override
	public List<RequestSO> getModeratedRequestsByUser(UserSO user) {
		List<Request> modelList = requestDao.findModeratedRequestsByUser(user.convertToModelObject());
		List<RequestSO> soList = new ArrayList<RequestSO>();
		for (Request model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	
	@Override
	public RequestPostSO saveRequestPost(Long requestId,Long userId, String post) {
		Request request = requestDao.findRequestById(requestId);
		User user = userDao.findUserById(userId);
		RequestPost requestPost = new RequestPost();
		requestPost.setRequest(request);
		requestPost.setContext(post);
		requestPost.setUser(user);
		
		RequestPost model = requestDao.saveRequestPost(requestPost);
		
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}
	/**
	 * Saves the request with request, user id and amount of the good.
	 * @param request
	 * @param userId
	 * @param goodsAmount
	 */
	@Override
	public RequestResponseSO saveRequestResponse(RequestSO request, Long userId, int goodsAmount) {
		RequestResponse requestResponse = new RequestResponse();
		requestResponse.setRequest(request.convertToModelObject());
		requestResponse.setUser(userDao.findUserById(userId));
		requestResponse.setRespondAmount(goodsAmount);
		RequestResponse model = requestDao.saveRequestResponse(requestResponse);
		if(model != null){
			addToRespondedAmountOfRequest(request,goodsAmount);
			return model.convertToServiceObject();
		}
		return null;
	}
	/**
	 * Adds the amount of responded request.
	 * @param request
	 * @param amount
	 */
	private void addToRespondedAmountOfRequest(RequestSO request,int amount) {
		Request model = requestDao.findRequestById(request.getId());
		if(request.getActivityType() == ActivityType.GOODS){
			Goods goods = model.getGoods();
			goods.setRespondedAmount(goods.getRespondedAmount() + amount);
			activityDao.updateGoods(goods);
		}
		else if(request.getActivityType() == ActivityType.SERVICES){
			Services services = model.getService();
			services.setRespondedAmount(services.getRespondedAmount() + amount);
			activityDao.updateServices(services);
		}
	}

	@Override
	public ArrayList<RequestResponseSO> getRequestResponsesByUserIdAndRequestId(Long userId, Long requestId) {
		ArrayList<RequestResponse> modelList = (ArrayList<RequestResponse>) requestDao.findRequestResponsesByUserIdAndRequestId(userId,requestId);
		ArrayList<RequestResponseSO> soList = new ArrayList<RequestResponseSO>();
		for (RequestResponse requestResponse : modelList) {
			soList.add(requestResponse.convertToServiceObject());
		}
		return soList;
	}
	
	@Override
	public List<UserSO> getModeratorsByRequestId(Long requestId) {
		List<User> modelList = requestDao.findModeratorsByRequestId(requestId);
		List<UserSO> soList = new ArrayList<UserSO>();
		for (User model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	
	@Override
	public void updateRequest(RequestSO request) {
		
		Goods goods = null;
		Services service = null;
		
		if(request.getGoods() != null) {
			goods = activityDao.findGoodByRequestId(request.getId());
			if(goods == null){
				goods = activityDao.saveGoods(request.getGoods().convertToModelObject());
			}else{
				request.getGoods().setId(goods.getId());
				activityDao.mergeGoods(request.getGoods().convertToModelObject());
			}
			
		}
		if(request.getService() != null) {
			Services findedService = activityDao.findServiceByRequestId(request.getId());
			SkillSO skillSO = request.getService().getRequiredSkill();
			if(findedService == null){
				
				Skill skill = activityDao.saveSkill(skillSO.convertToModelObject());
				service = request.getService().convertToModelObject();
				service.setRequiredSkill(skill);
				service = activityDao.saveService(service);
			}else{
				
				request.getService().setId(findedService.getId());
				skillSO.setId(activityDao.findSkillByServiceId(request.getService().getId()).getId());
				Skill skill = skillSO.convertToModelObject();
				activityDao.mergeSkill(skill);
				service = request.getService().convertToModelObject();
				service.setRequiredSkill(skill);
				activityDao.mergeServices(service);
			}
			
		}
		Request model = request.convertToModelObject();
		model.setGoods(goods);
		model.setService(service);
		
		requestDao.updateRequest(model);
		
	}

	@Override
	public RequestSO getModeratedRequestByRequestIdAndUserId(Long requestId, Long userId) {
		Request model = requestDao.findModeratedRequestByRequestIdAndUserId(requestId, userId);
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}
}
